package cn.javabb.web.controller;

import cn.hutool.core.util.StrUtil;
import cn.javabb.common.exception.BusinessException;
import cn.javabb.core.base.BaseController;
import cn.javabb.core.entity.sys.UserDO;
import cn.javabb.core.model.LoginType;
import cn.javabb.core.plugin.oauth.RequestFactory;
import cn.javabb.core.service.sys.UserAuthService;
import cn.javabb.core.service.sys.UserService;
import cn.javabb.core.shiro.UserToken;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 第三方登陆
 */
@Slf4j
@Controller
@RequestMapping("/oauth")
public class OAuthController extends BaseController {
    @Autowired
    private UserService userService;
    @Autowired
    private UserAuthService userAuthService;

    @GetMapping("/render/{source}")
    public void renderAuth(@PathVariable("source") String source, HttpServletResponse response, HttpSession session)throws IOException {
        AuthRequest authRequest = RequestFactory.getInstance(source).getRequest();
        //session.setAttribute("historyUrl",RequestUtil.getReferer());
        response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
    }
    @GetMapping("/callback/{source}")
    public Object login(@PathVariable("source") String source, AuthCallback callback,
                        HttpSession session,
                        HttpServletResponse response) throws IOException {
        AuthRequest authRequest = RequestFactory.getInstance(source).getRequest();
        AuthResponse authResponse = authRequest.login(callback);
        String historyUrl = (String) session.getAttribute("historyUrl");
        session.removeAttribute("historyUrl");
        // 支付宝登录时，返回auth_code
        log.info("准备第三方登陆===》");
        if(authResponse.ok()){
            AuthUser authUser = (AuthUser) authResponse.getData();
            UserDO loginUser = getLoginUser();
            if (null == loginUser) { // 三方登陆
                UserDO newUser  = userAuthService.userAuth(authUser);
                UserToken token = new UserToken(newUser.getUserName(),"", LoginType.OAUTH.getDesc());
                // 获取当前的Subject
                Subject currentUser = SecurityUtils.getSubject();
                try {
                    log.info("对用户[" + newUser.getUserName() + "]进行登录验证..验证开始");
                    currentUser.login(token);
                    log.info("对用户[" + newUser.getUserName() + "]进行登录验证..验证通过");
                }catch (Exception ex){
                    ex.printStackTrace();
                    log.error("第三方登陆失败==》authId = {} ,",authUser.getUuid());
                    throw new BusinessException("第三方登陆失败"+ex);
                }
                if (StrUtil.isNotBlank(historyUrl)){
                    return "redirect:"+historyUrl;
                }
                return "redirect:/";
            }else{ // 授权登陆
                String state = "";
                if(userAuthService.getUserAuthByAuthId(authUser.getUuid()) != null){ // 已经绑定了授权
                    return "redirect:/user/oauth/?state=error_701";
                }
                if(userAuthService.userBindAuth(authUser,loginUser)){
                    state = "ok";
                }else{
                    state = "error";
                }
                return "redirect:/user/oauth/?state="+state;
            }
        }
        return "redirect:/";
    }
    /**
     * 收回授权
     *
     * @param source
     * @return
     * @throws IOException
     */
    @RequiresAuthentication
    @RequestMapping("/revoke/{source}")
    public Object revokeAuth(@PathVariable("source") String source) throws IOException {
        UserDO loginUser = getLoginUser();
        if(userAuthService.revokeAuth(source,loginUser.getId())){
            return "redirect:/user/oauth/?state=ok_201";
        }
        return "redirect:/user/oauth/?state=error_702";

    }

}
